/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/


typedef enum m_state_e
{
	m_none,
	m_main,
	m_singleplayer,
	m_load,
	m_save,
	m_multiplayer,
	m_setup,
	m_options,
	m_video,
	m_keys,
	m_help,
	m_quit,
	m_joingame,
	m_startgame,
	m_gameoptions,
	m_search,
	m_slist,
	MAX_MENUS
} m_state_t;


enum m_soundlevel_t
{
	m_sound_none,
	m_sound_navigate,
	m_sound_enter,
	m_sound_alert,
	m_sound_adjust,
	m_sound_quit
};


extern m_soundlevel_t m_soundlevel;


class CMenuValueList
{
private:
	std::vector<int> values;
	BOOL dirty;
	int option;

	void Clean (void);

public:
	CMenuValueList (void);
	BOOL Find (int val);
	int GetCurrent (void);
	void Adjust (int dir);
	void SetCvar (cvar_t *var);
	void Append (int val);
};


void M_AdjustCvar (cvar_t *var, float adj, float minval, float maxval);
void M_DrawCharacter (int cx, int line, int num);
void M_Print (int cx, int cy, char *str);
void M_PrintJustified (int cx, int cy, char *str);
void M_PrintWhite (int cx, int cy, const char *str);
void M_DrawPic (int x, int y, qpic_t *pic);
void M_DrawBanner (char *name);
void M_DrawSmallCursor (int x, int y, int c = 12);
void M_DrawHighlight (int y, int width = 400);
void M_DrawHighlight (int x, int y, int width);
void M_DrawCommand (int y, char *text);
void M_DrawCheckbox (int y, char *text, BOOL on);
void M_DrawValueList (int y, char *text, CMenuValueList &list);
void M_DrawStringOption (int y, char *text = NULL, char *stringoption = NULL);
void M_DrawDivider (int y);
void M_DrawCenteredPic (int y, qpic_t *pic);
void M_DrawTextBox (int x, int y, int width, int lines);
void M_DrawMapshot (int x, int y, char *name);
void M_ToggleMenu_f (void);

char *M_GetSkill (int sk);
char *M_GetSkill (void);
void M_DrawLabelValue (int labelx, int valuex, int y, char *label, char *value);


class qmenu_option_t
{
public:
	qmenu_option_t () {this->Visible = TRUE; this->Active = TRUE;}
	virtual int Draw (int y) = 0;
	virtual BOOL Key (int key) = 0;
	virtual void DrawHighlight (int y);

	void SetVisibleForTag (int tag, BOOL visible);
	void SetTag (int newtag);
	BOOL IsActive (void);
	BOOL IsVisible (void);

protected:
	char Text[64];
	BOOL Active;
	int Tag;
	BOOL Visible;
};


class qmenu_textbox_base_t : public qmenu_option_t
{
public:
	qmenu_textbox_base_t (char *label, char *textboxtext, int length);
	int Draw (int y);
	virtual BOOL Key (int key) = 0;
	void DrawHighlight (int y);

protected:
	BOOL CommonKey (int key, int minkey, int maxkey);
	char *TextboxText;
	int Length;
	BOOL IsHighLight;
};


class qmenu_textbox_t : public qmenu_textbox_base_t
{
public:
	qmenu_textbox_t (char *label, char *textboxtext, int length) : qmenu_textbox_base_t (label, textboxtext, length) {}
	BOOL Key (int key) {return this->CommonKey (key, 32, 127);}
};


class qmenu_numericbox_t : public qmenu_textbox_base_t
{
public:
	qmenu_numericbox_t (char *label, char *textboxtext, int length) : qmenu_textbox_base_t (label, textboxtext, length) {}
	BOOL Key (int key) {return this->CommonKey (key, '0', '9');}
};


class qmenu_submenu_t : public qmenu_option_t
{
public:
	qmenu_submenu_t (char *text, m_state_t submenu);
	int Draw (int y);
	BOOL Key (int key);

protected:
	m_state_t SubMenu;
};


class qmenu_bigsubmenu_t : public qmenu_option_t
{
public:
	qmenu_bigsubmenu_t (m_state_t submenu);
	int Draw (int y) {return y + 20;}
	BOOL Key (int key);
	void DrawHighlight (int y);

protected:
	m_state_t SubMenu;
};


class qmenu_stringoptionwatcher_t
{
public:
	virtual char *GetFunc (void) = 0;
	virtual void SetFunc (int dir) = 0;
};


class qmenu_stringoption_t : public qmenu_option_t
{
public:
	qmenu_stringoption_t (char *text, qmenu_stringoptionwatcher_t &watcher);
	int Draw (int y);
	BOOL Key (int key);
	void DrawHighlight (int y);

protected:
	qmenu_stringoptionwatcher_t *Watcher;
};


class qmenu_dynamictext_t : public qmenu_option_t
{
public:
	qmenu_dynamictext_t (char *text);
	int Draw (int y);
	BOOL Key (int key) {return FALSE;}

protected:
	char *DynamicText;
};


class qmenu_textlabel_t : public qmenu_option_t
{
public:
	qmenu_textlabel_t (char *label, char *text);
	int Draw (int y);
	BOOL Key (int key) {return FALSE;}

protected:
	char *DynamicText;
};


class qmenu_action_t : public qmenu_option_t
{
public:
	qmenu_action_t (char *text, void (*action) (void));
	int Draw (int y);
	BOOL Key (int key);

protected:
	void (*Action) (void);
};


class qmenu_bigaction_t : public qmenu_option_t
{
public:
	qmenu_bigaction_t (void (*action) (void));
	int Draw (int y) {return y + 20;}
	BOOL Key (int key);
	void DrawHighlight (int y);

protected:
	void (*Action) (void);
};


class qmenu_slider_t : public qmenu_option_t
{
public:
	qmenu_slider_t (char *text, char *var, float minval, float maxval, float step);
	int Draw (int y);
	BOOL Key (int key);

protected:
	char Var[64];
	float MinVal;
	float MaxVal;
	float Step;
};


class qmenu_checkboxwatcher_t
{
public:
	virtual BOOL GetFunc (void) = 0;
	virtual void SetFunc (void) = 0;
};


class qmenu_checkbox_t : public qmenu_option_t
{
public:
	qmenu_checkbox_t (char *text, qmenu_checkboxwatcher_t &watcher);
	int Draw (int y);
	void DrawHighlight (int y);
	BOOL Key (int key);

private:
	qmenu_checkboxwatcher_t *Watcher;
};


class qmenu_divider_t : public qmenu_option_t
{
public:
	qmenu_divider_t (void);
	int Draw (int y);
	BOOL Key (int key) {return FALSE;}
};


class qmenu_banner_t : public qmenu_option_t
{
public:
	qmenu_banner_t (char *name);
	int Draw (int y);
	BOOL Key (int key) {return FALSE;}
};


class qmenu_chunkypic_t : public qmenu_option_t
{
public:
	qmenu_chunkypic_t (char *name);
	int Draw (int y);
	BOOL Key (int key) {return FALSE;}
};


class qmenu_plaque_t : public qmenu_option_t
{
public:
	qmenu_plaque_t (void);
	int Draw (int y);
	BOOL Key (int key) {return FALSE;}
};


class qmenu_t
{
public:
	virtual void EnterFunc (void) = 0;

	void Draw (void);
	void Key (int key);
	void LeaveMenu (void);

protected:
	virtual void CustomDraw (void) {/* may be overridden by derived classes*/};
	virtual BOOL KeyFunc (int key) {return FALSE; /* may be overridden by derived classes*/};

	void Register (m_state_t state);
	virtual void Navigate (int dir);
	void EnterMenu (void);

	void AddOption (qmenu_option_t *option, int tag = 0);
	void ShowOptions (int tag);
	void HideOptions (int tag);

	std::vector<qmenu_option_t *> Options;
	int ActiveOption;

	m_state_t State;
};


extern qmenu_t *menus[MAX_MENUS];
extern int m_save_demonum;

void M_ConfigureNetSubsystem (void);

extern int menu_ofsy;

extern m_state_t m_state;

extern BOOL	m_recursiveDraw;

extern m_state_t	m_return_state;
extern BOOL			m_return_onerror;
extern char			m_return_reason[32];

// these are just shortcuts for entering menus from commands
__inline void M_Menu_Main_f (void) {menus[m_main]->EnterFunc ();}
__inline void M_Menu_SinglePlayer_f (void) {menus[m_singleplayer]->EnterFunc ();}
__inline void M_Menu_Save_f (void) {menus[m_load]->EnterFunc ();}
__inline void M_Menu_Load_f (void) {menus[m_save]->EnterFunc ();}
__inline void M_Menu_MultiPlayer_f (void) {menus[m_multiplayer]->EnterFunc ();}
__inline void M_Menu_Setup_f (void) {menus[m_setup]->EnterFunc ();}
__inline void M_Menu_Options_f (void) {menus[m_options]->EnterFunc ();}
__inline void M_Menu_Video_f (void) {menus[m_video]->EnterFunc ();}
__inline void M_Menu_Keys_f (void) {menus[m_keys]->EnterFunc ();}
__inline void M_Menu_Help_f (void) {menus[m_help]->EnterFunc ();}
__inline void M_Menu_Quit_f (void) {menus[m_quit]->EnterFunc ();}
__inline void M_Menu_JoinGame_f (void) {menus[m_joingame]->EnterFunc ();}
__inline void M_Menu_StartGame_f (void) {menus[m_startgame]->EnterFunc ();}
__inline void M_Menu_GameOptions_f (void) {menus[m_gameoptions]->EnterFunc ();}
__inline void M_Menu_Search_f (void) {menus[m_search]->EnterFunc ();}
__inline void M_Menu_ServerList_f (void) {menus[m_slist]->EnterFunc ();}

